#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>

#define DTSBACKLIGHT_NAME	"dtsbacklight" 
#define DTSBACKLIGHT_CNT	1

struct dtsbacklight_st
{
	int major;
	int minor;
	dev_t devid;
	struct cdev cdev;
	struct class *class;
	struct device *device;
	struct device_node *node;
};

static ssize_t dtsbacklight_read(struct file *flip, char __user *buf, size_t cnt, loff_t *off_t)
{

	return 0;
}

static ssize_t dtsbacklight_write(struct file *flip, const char __user *buf, size_t cnt, loff_t *off_t)
{

	return 0;
}

static int dtsbacklight_open(struct inode *inode, struct file *flip)
{

	return 0;
}

static int dtsbacklight_release(struct inode *inode, struct file *flip)
{

	return 0;
}

static struct dtsbacklight_st dtsbacklight;
static struct file_operations dtsbacklight_fops = 
{
	.owner 		= THIS_MODULE,
	.read		= dtsbacklight_read,
	.write 		= dtsbacklight_write,
	.open 		= dtsbacklight_open,
	.release 	= dtsbacklight_release,
};

static int __init  dtsbacklight_init(void)
{
	struct property *proper;
	int ret=0,i=0;
	const char *str;
	u32 data[8]={0};

	//获取设备节点
	dtsbacklight.node = of_find_node_by_path("/backlight");
	if(dtsbacklight.node ==NULL)
	{
		printk("of_find_node_by_path error\r\n");
		return -EINVAL;
	}
	printk("of_find_node_by_path sucess\r\n");

	proper = of_find_property(dtsbacklight.node, "compatible", NULL);
	if(proper ==NULL)
	{
		printk("of_find_property error\r\n");
	}
	printk("compatible:%s\r\n",(char *)proper->value);

	ret = of_property_read_string(dtsbacklight.node, "status", &str);
	if(ret<0)
	{
		printk("of_property_read_string error\r\n");
	}
	printk("status:%s\r\n",str);

	ret = of_property_read_u32_array(dtsbacklight.node, "brightness-levels", data, 8);
	if(ret<0)
	{
		printk("of_property_read_u8_array error\r\n");
	}
	for(i=0;i<8;i++)
	{
		printk("brightness-levels[%d]:%d",i,data[i]);
	}

	//申请设备号
	if(dtsbacklight.major)
	{
		dtsbacklight.devid = MKDEV(dtsbacklight.major, 0);
		ret = register_chrdev_region(dtsbacklight.devid, DTSBACKLIGHT_CNT, DTSBACKLIGHT_NAME);
		if(ret <0)
		{

		}
	}
	else
	{
		ret = alloc_chrdev_region(&dtsbacklight.devid, 0, DTSBACKLIGHT_CNT, DTSBACKLIGHT_NAME);
		if(ret <0)
		{

		}
		dtsbacklight.major = MAJOR(dtsbacklight.devid);
		dtsbacklight.minor = MINOR(dtsbacklight.devid);
	}

	//创建字符设备
	dtsbacklight.cdev.owner = THIS_MODULE;
	cdev_init(&dtsbacklight.cdev, &dtsbacklight_fops);
	ret = cdev_add(&dtsbacklight.cdev, dtsbacklight.devid, DTSBACKLIGHT_CNT);
	if(ret <0)
	{

	}

	//创建类
	dtsbacklight.class = class_create(THIS_MODULE, DTSBACKLIGHT_NAME);
	if(IS_ERR(dtsbacklight.class))
	{
		return PTR_ERR(dtsbacklight.class);
	}

	//创建设备
	dtsbacklight.device = device_create(dtsbacklight.class, NULL, dtsbacklight.devid, NULL, DTSBACKLIGHT_NAME);
	if(IS_ERR(dtsbacklight.device))
	{
		return PTR_ERR(dtsbacklight.device);
	}

	printk("dtsbacklight init sucess\r\n");

	return 0;
}

static void __exit dtsbacklight_exit(void)
{
	//卸载字符设备
	cdev_del(&dtsbacklight.cdev);
	unregister_chrdev_region(dtsbacklight.devid, DTSBACKLIGHT_CNT);

	//卸载设备节点
	device_destroy(dtsbacklight.class, dtsbacklight.devid);
	class_destroy(dtsbacklight.class);
	
	printk("dtsbacklight exit sucess\r\n");
}

module_init(dtsbacklight_init);
module_exit(dtsbacklight_exit);
MODULE_AUTHOR("jtb");
MODULE_LICENSE("GPL");

